using ElementaryMath;
using System;
using System.Data;

namespace HigherMathmatics
{
    namespace MeanValueTheorem
    {
        public class TaylorsFormula : Function
        {
            private Function func;
            private int n;
            private double x_0;
            private Function taylor;
            public TaylorsFormula(Function func, int n, double x_0)
            {
                this.func = func;
                this.n = n;
                this.x_0 = x_0;
                this.taylor = new Constant(this.func.Calculate(this.x_0));
                for (int i = 1; i <= this.n; i++)
                {
                    Function c = new Constant(this.func.DerivativeFunction(i).Calculate(this.x_0));

                    this.taylor = new Add(this.taylor, new Mul(new Div(new Constant(this.func.DerivativeFunction(i).Calculate(this.x_0)), new Constant(Constants.Factorial(i))), new Pow(new Sub(new X(), new Constant(this.x_0)), i)));
                    this.taylor = this.taylor.simaplify();
                }

            }

            public double epsilon(double x)
            {
                double left = Math.Min(this.x_0, x);
                double right = Math.Max(this.x_0, x);
                double step = (right - left) / 100;
                double max = 0;
                Function dir = this.func.DerivativeFunction(this.n+1);
                for (double i = left; i <= right; i += step)
                {
                    double val = Math.Abs(dir.Calculate(i));
                    if (val > max)
                    {
                        max = val;
                    }
                }
                return max / Constants.Factorial(n + 1) * Math.Pow(Math.Abs(x-this.x_0),n+1);
            }
            public override double Calculate(double x)
            {
                return this.taylor.Calculate(x);
            }

            public override Function DerivativeFunction(int n)
            {
                return this.taylor.DerivativeFunction(n);
            }

            public override Function simaplifyOnce()
            {
                return this.taylor.simaplifyOnce();
            }

            public override string ToString()
            {
                return this.taylor.ToString();
            }
        }
    }
}
